/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package utilities;

import utilities.entities.XDate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author olawale
 */
public class Generator {

    public static DefaultTableModel generate(Date startDate, int years, int columns, int divisible){
        DefaultTableModel dtm = addDefaultColumns(columns);
        setColumns(startDate, dtm, columns, years, divisible);
        return dtm;
    }

    private static DefaultTableModel addDefaultColumns(int col){
        ArrayList<String> columnNames = new ArrayList();
        columnNames.add("");
        columnNames.add("Date");
        columnNames.add("MON A");
        columnNames.add("MON B");
        columnNames.add("MARKING");
        for(int i = 1; i <= col; i++){
            columnNames.add("COL " + i);
        }

        DefaultTableModel dtm = new DefaultTableModel(new Object [][] {}, columnNames.toArray()){
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };

        return dtm;
    }


    private static void setColumns(Date startDate, DefaultTableModel dtm, int ncol, int years, int divisible){
        ArrayList<Date> dateList = new ArrayList();
        ArrayList<XDate> xdateList = new ArrayList();
        SimpleDateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy");
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        int i = 0;
        do{
            dtm.addRow(new Object [] {++i, df.format(cal.getTime()), i});
            dateList.add(cal.getTime());
            xdateList.add(new XDate(cal.getTime()));
            cal.add(Calendar.DAY_OF_MONTH, 7);
        }while(cal.get(Calendar.YEAR) <= years);


        if(divisible > 0){
            int step = 0;
//            System.out.println("...divisible");
//            System.out.println("rows " + dtm.getRowCount());
            ArrayList<Integer> inserts = new ArrayList();
            for(int r = 0; r < dtm.getRowCount(); r++){
                if(step == 0){
                    int a = ((r-5) < 0) ? 0 : (r-5);
                    int b = ((r+5) > dtm.getRowCount()) ? dtm.getRowCount() : (r+5);
                    List<Date> list = dateList.subList(a, b);
                    Date cdate = dateList.get(r);
                    int count = getDaysCount(list, cdate);
                    if(count == 4){
                        Date lastDate = getLastDate(list, cdate);
                        int LDIndex = dateList.indexOf(lastDate);
//                        dtm.insertRow(LDIndex+1, new Object [] {0, "new date", 0, LDIndex});
                        inserts.add(LDIndex);
//                        System.out.print("row: " + (r+1));
//                        System.out.println(" lastDate: " + lastDate + " lastDateIndex: " + (LDIndex + 1));
                    }
                }
                dtm.setValueAt(++step, r, 4);
                if(step == divisible) step = 0;
            }

//            System.out.println("inserts" + inserts);
            int pos = 0;
            for(int in : inserts){
                in = ++in + pos;
                dtm.insertRow((in), new Object [] {0, "new date", 0, in});
                Object indx = dtm.getValueAt((in-1), 4);
                dtm.setValueAt(indx, (in), 4);
                dateList.add(in, dateList.get(in-1));
                xdateList.add(in, xdateList.get(in-1).addWeek());
                dtm.setValueAt(xdateList.get(in).toString(), in, 1);
                ++pos;
            }

            int indx = 0;
            for(int ri = 0; ri < dtm.getRowCount(); ri++){
                dtm.setValueAt(++indx, ri, 0);
                dtm.setValueAt(indx, ri, 2);
            }

            
        }


        int rows = dtm.getRowCount();
        for(int r = 0; r < dtm.getRowCount(); r++){
            dtm.setValueAt(rows--, r, 3);
        }

        cal.setTime(dateList.get(0));
        int startMonth = cal.get(Calendar.MONTH);
        int startYear = cal.get(Calendar.YEAR);
        int cm = startMonth;
        ArrayList listList = new ArrayList();
        ArrayList tmpList = null;

        for(int col = 5; col < dtm.getColumnCount(); col++){
            int nm = 0, ser = 0;
             tmpList = new ArrayList();
            for(int row = 0; row < dateList.size(); row++){

                cal.setTime(dateList.get(row));
                int currentMonth = cal.get(Calendar.MONTH);
                int currentYear = cal.get(Calendar.YEAR);
                if(startYear > currentYear){
                    tmpList.add(-1);
                    continue;
                }
                if((currentMonth < startMonth) && ser == 0){
                    tmpList.add(-1);
//                    dtm.setValueAt(new Object[]{"-", "-"}, row, col);
                    continue;
                }
                ++ser;
                if(cm != currentMonth){
                    ++nm;
                    cm = currentMonth;
                }

                if(nm == ncol){
                    nm = 0;
                    ser = 1;
                }
                tmpList.add(ser);
//                dtm.setValueAt(new Object[]{ser, ""}, row, col);

            }
            listList.add(tmpList);
            startMonth = ++startMonth % 12;
            cm = startMonth;
            if(startMonth == 0) ++startYear;
        }
        fillColumns(dtm, listList);
    }

    private static void fillColumns(DefaultTableModel dtm, ArrayList<ArrayList> listList){
//        System.out.println("fill columns");
        int row = 0, col = 5;
        for(ArrayList<Integer> arrayList : listList){
            row = 0;
            while(arrayList.get(row) == -1){
                dtm.setValueAt(new Object[]{"", ""}, row++, col);
//                System.out.println(row);
            }
//            System.out.println("size: " + arrayList.size() + "   col: " + col);
            while(true){
                int firstIndx = arrayList.indexOf(1);
                if(firstIndx == -1)break;
                arrayList.remove(firstIndx);
                int lastIndx = arrayList.indexOf(1);
                if(lastIndx == -1)lastIndx = arrayList.size();
                Object [] list = arrayList.subList(firstIndx, lastIndx).toArray();
                arrayList.subList(firstIndx, lastIndx).clear();
                int a = 1, b = list.length + 1;
                dtm.setValueAt(new Object[]{a, b}, row++, col);
                for(Object i : list){
                    dtm.setValueAt(new Object[]{++a, --b}, row++, col);
                }
            }
            ++col;
        }
    }

    private static int getDaysCount(List<Date> list, Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month = cal.get(Calendar.MONTH);
        int count = 0;
        for(Date d : list){
            cal.setTime(d);
            if(month == cal.get(Calendar.MONTH))
                ++count;
        }
        return count;
    }

    public static Date getLastDate(List<Date> list, Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month = cal.get(Calendar.MONTH);
        Date lastDate = null;
        for(Date d : list){
            cal.setTime(d);
            if(month == cal.get(Calendar.MONTH))
                lastDate = d;
            else
                continue;
        }
        return lastDate;
    }
}
